//
//  CoGePSBrushesPlugIn.m
//  CoGePSBrushes
//
//  Created by Tamas Nagy on 7/2/09.
//  Copyright (c) 2009 __MyCompanyName__. All rights reserved.
//

/* It's highly recommended to use CGL macros instead of changing the current context for plug-ins that perform OpenGL rendering */
#import <OpenGL/CGLMacro.h>

#import "CoGePSBrushesPlugIn.h"
#import "BrushFile.h"

#define	kQCPlugIn_Name				@"CoGePSBrushes"
#define	kQCPlugIn_Description		@"Readings the brushes from a .abr file to a QC structure. If the Width or the Height parameters 0, the image will created with the original size, elsewhere the output images will be fitted."

@implementation CoGePSBrushesPlugIn

/*
Here you need to declare the input / output properties as dynamic as Quartz Composer will handle their implementation
@dynamic inputFoo, outputBar;
*/

@dynamic inputPath, inputWidth, inputHeight, outputArray;

@synthesize outArray;

+ (NSDictionary*) attributes
{
	/*
	Return a dictionary of attributes describing the plug-in (QCPlugInAttributeNameKey, QCPlugInAttributeDescriptionKey...).
	*/
	
	return [NSDictionary dictionaryWithObjectsAndKeys:kQCPlugIn_Name, QCPlugInAttributeNameKey, kQCPlugIn_Description, QCPlugInAttributeDescriptionKey, nil];
}

+ (NSDictionary*) attributesForPropertyPortWithKey:(NSString*)key
{
	/*
	Specify the optional attributes for property based ports (QCPortAttributeNameKey, QCPortAttributeDefaultValueKey...).
	*/
	
	if([key isEqualToString:@"inputPath"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeString, QCPortAttributeTypeKey,
				@"File Location", QCPortAttributeNameKey,				
				@"",  QCPortAttributeDefaultValueKey,
				
				nil];

	if([key isEqualToString:@"inputWidth"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeNumber, QCPortAttributeTypeKey,
				@"Width", QCPortAttributeNameKey,
				[NSNumber numberWithDouble:0], QCPortAttributeDefaultValueKey,
				
				nil];

	if([key isEqualToString:@"inputHeight"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				QCPortTypeNumber, QCPortAttributeTypeKey,
				@"Height", QCPortAttributeNameKey,
				[NSNumber numberWithDouble:0], QCPortAttributeDefaultValueKey,
				
				nil];	
	
    if([key isEqualToString:@"outputArray"])
		
        return [NSDictionary dictionaryWithObjectsAndKeys:
				
				@"Brushes", QCPortAttributeNameKey,
				
				nil];

	
	return nil;
}

+ (NSArray*) sortedPropertyPortKeys
{
	return [NSArray arrayWithObjects:@"inputPath",
			@"inputWidth",
			@"inputHeight",
			@"outputArray",nil];
}


+ (QCPlugInExecutionMode) executionMode
{
	/*
	Return the execution mode of the plug-in: kQCPlugInExecutionModeProvider, kQCPlugInExecutionModeProcessor, or kQCPlugInExecutionModeConsumer.
	*/
	
	return kQCPlugInExecutionModeProcessor;
}

+ (QCPlugInTimeMode) timeMode
{
	/*
	Return the time dependency mode of the plug-in: kQCPlugInTimeModeNone, kQCPlugInTimeModeIdle or kQCPlugInTimeModeTimeBase.
	*/
	
	return kQCPlugInTimeModeIdle;
}

- (id) init
{
	if(self = [super init]) {
		/*
		Allocate any permanent resource required by the plug-in.
		*/
	}
	
	return self;
}

- (void) finalize
{
	/*
	Release any non garbage collected resources created in -init.
	*/
	
	[super finalize];
}

- (void) dealloc
{
	/*
	Release any resources created in -init.
	*/
	
	[super dealloc];
}

@end

@implementation CoGePSBrushesPlugIn (Execution)

//get the brushez
-(void)getBrushesFromFile:(NSString *)fileName {
	
	NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
	
	
	float width, height;
	width = self.inputWidth;
	height = self.inputHeight;
	
	BOOL isDir;
	
	if ([[NSFileManager defaultManager] fileExistsAtPath:fileName isDirectory:&isDir] && !isDir) {
		
		//trying to get brushes
		@try {
			
			BrushFile *theBrush = [[BrushFile alloc] init];
			[theBrush parseBrushFile:fileName];
			
			self.outArray = [theBrush getImagesWithWidth:width andHeight:height];
			[theBrush release];
			
		}
		
		@catch (NSException * e) {
			
			NSLog(@"unsupported format or not a brush file...");
			
			self.outArray = nil;

		}
		
	} else {
		
		self.outArray = nil;
	}
	
	[pool release];
	
}


- (BOOL) startExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when rendering of the composition starts: perform any required setup for the plug-in.
	Return NO in case of fatal failure (this will prevent rendering of the composition to start).
	*/
	
	
	return YES;
}

- (void) enableExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when the plug-in instance starts being used by Quartz Composer.
	*/
}

- (BOOL) execute:(id<QCPlugInContext>)context atTime:(NSTimeInterval)time withArguments:(NSDictionary*)arguments
{
	/*
	Called by Quartz Composer whenever the plug-in instance needs to execute.
	Only read from the plug-in inputs and produce a result (by writing to the plug-in outputs or rendering to the destination OpenGL context) within that method and nowhere else.
	Return NO in case of failure during the execution (this will prevent rendering of the current frame to complete).
	
	The OpenGL context for rendering can be accessed and defined for CGL macros using:
	CGLContextObj cgl_ctx = [context CGLContextObj];
	*/
	
	
	if ((([self didValueForInputKeyChange:@"inputWidth"]) || ([self didValueForInputKeyChange:@"inputHeight"]) ) || ([self didValueForInputKeyChange:@"inputPath"])) {
	
		NSLog(@"get brushes...");
		
		if([self.inputPath isAbsolutePath])
		{
			//if path is absolute
			[NSThread detachNewThreadSelector:@selector(getBrushesFromFile:) toTarget:self withObject:[NSString stringWithString:self.inputPath]];
			
		}
		else
		{
			//okay, its a relative path
			//[self getBrushesFromFile:[NSString pathWithComponents:[NSArray arrayWithObjects:[[[context compositionURL] path] stringByDeletingLastPathComponent], self.inputPath, nil]]];
			[NSThread detachNewThreadSelector:@selector(getBrushesFromFile:) toTarget:self withObject:[NSString stringWithString:[NSString pathWithComponents:[NSArray arrayWithObjects:[[[context compositionURL] path] stringByDeletingLastPathComponent], self.inputPath, nil]]]];
		}
	
	}
	
	@synchronized (self.outArray) {
		
		self.outputArray = self.outArray;
	
	}
	
	
	
	return YES;
}

- (void) disableExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when the plug-in instance stops being used by Quartz Composer.
	*/
}

- (void) stopExecution:(id<QCPlugInContext>)context
{
	/*
	Called by Quartz Composer when rendering of the composition stops: perform any required cleanup for the plug-in.
	*/
}

@end
